#include "server.h"
#include "defines.h"
#include "errno.h"
#include "stdio.h"
#include "string.h"
#include <fcntl.h>
#include <unistd.h>
#include <signal.h>
#include <stdlib.h>


extern "C"{
    static bool runMainLoop;
    void intHandler(int sigNum){
        UNUSED(sigNum)
        runMainLoop = false;        
    }
}


Server::Server():
        fifo_(-1)
{
    runMainLoop = true;
    signal(SIGINT, intHandler);
}

Server* Server::getInstance(){
    static Server instance;
    return &instance;
}

int Server::init(){
    if(mkfifo(DLM_PIPE_NAME, S_IREAD | S_IWRITE) != 0 && errno != EEXIST){
        fprintf(stderr, "Błąd tworzenia kolejki FIFO: %s\n", strerror(errno));
        return -1;
    }

    fifo_ = open(DLM_PIPE_NAME, O_RDWR | O_NONBLOCK);
    if (fifo_ == -1){
        fprintf(stderr, "Błąd otwarcia kolejki FIFO: %s\n", strerror(errno));
        return -1;
    }
    return 0;
}

int Server::run(){
    fd_set readFiles;
    FD_ZERO(&readFiles);
    FD_SET(fifo_, &readFiles);
    const int maxFd = fifo_ + 1;
    long timeout = 0;
    while(true){
        setTimeout(timeout);
        fprintf(stdout, "Czekam na wiadomość %ld\n", timeout);
        if(select(maxFd, &readFiles, NULL, NULL, (timeout==0 ? NULL : &timeout_) ) == -1){
            fprintf(stderr, "Błąd oczekiwania na dane\n");
        }

        if(!runMainLoop){
            return 0;
        }else{
            RequestMsg msg;
            if(FD_ISSET(fifo_, &readFiles)){
                int readStatus = 0;
                readStatus = readRequest(fifo_, &msg);
                if(readStatus == 0){
                    handler_.handleMsg(msg);
                }else{
                    fprintf(stderr, "Błąd odczytu danych z FIFO\n");
                }
            }else{
                fprintf(stdout, "Brak danych do odczytu\n");
                handler_.handleTimeout();
                FD_SET(fifo_, &readFiles);
            }

            timeout = handler_.getTimeout();
        }
    }
    return 0;
}

void Server::setTimeout(long nanosec){
    long onlySec = nanosec / (1000 * 1000 * 1000);
    long onlyMicroSec = nanosec % (1000 * 1000);
    timeout_.tv_sec = onlySec;
    timeout_.tv_usec = onlyMicroSec;
    fprintf(stdout, "oczekuje %ld %ld\n", onlySec, onlyMicroSec);
}
